/* @(#)debug.c
 * Time-stamp: <2008-10-04 23:14:49 root>
 * Copyright 2008 Julian Qian
 * Author: root@localhost.localdomain
 * Version: $Id: debug.c,v 0.0 2008/09/27 17:04:13 root Exp $
 * Keywords: 
 */

#include "common.h"

int PrintLog(FILE* pfile, const char * pformat, ...){
	va_list _va_list;
	TIMESTRU timestru;
	char szBuf[MAXBUF];
	int nLen;
	if (pformat == NULL || pfile == NULL) return -1;
	timestru = GetTime();
	nLen = sprintf(szBuf, " %04d.%02d.%02d %02d:%02d:%02d [%d]: ",
		timestru.nYear, timestru.nMon, timestru.nDay,
		timestru.nHour, timestru.nMin, timestru.nSec, getpid());
		
	va_start(_va_list, pformat);
	nLen += vsprintf(szBuf+nLen, pformat, _va_list);
	va_end(_va_list);
	
	nLen += sprintf(szBuf + nLen, "\n");
	if (fputs(szBuf, pfile) != EOF && fflush(pfile) != EOF) return 0;
	return -2;
}

int PrintTraceLog(const char* pformat, ...){
 	va_list _va_list;
	char szBuf[MAXBUF];
 	FILE *fp;
 	int ret;
	if (pformat == NULL) return -1; 
		
 	va_start(_va_list, pformat);		  
 	vsprintf(szBuf, pformat, _va_list);     
 	va_end(_va_list);                      

 	if ((fp = fopen(TRACE_FILE, "a")) != NULL) {
 		ret = PrintLog(fp, szBuf);
 		fclose(fp);
	 	return(ret);
 	}
 	return -1;
}

int PrintHexLog(FILE* pfile, void * pData, int nSize){
	char cLine[16], *pcData;
	char szBuf[MAXBUF + 1];
	int nPos, nLineSize, nLine, nLen, n;
	if (pfile == NULL || pData == NULL) return -1;
	
	pcData = (char*)pData;
	nLine = 1;
	nLen = sprintf(szBuf, "address[%08X] size[%d]\n", pData, nSize);
	for (nPos = 0; nPos < nSize; nLine++) {
		nLineSize = min(nSize - nPos, 16);	
		memcpy(cLine, pcData + nPos, nLineSize);
		nPos += nLineSize;
		nLen += sprintf(szBuf + nLen, "[%02d]:  ", nLine);
		for (n = 0; n < nLineSize; n++)	{
			if (n == 8) nLen += sprintf(szBuf + nLen, " ");
			nLen += sprintf(szBuf + nLen, "%02X ", cLine[n] & 0x00FF);
		}
		for (n = nLineSize; n < 16; n++){
			if (n == 8) nLen += sprintf(szBuf + nLen, " ");
			nLen += sprintf(szBuf + nLen, "   ");
		}
		nLen += sprintf(szBuf + nLen, " :");
		for (n = 0; n < nLineSize; n++)	{
			if (!isprint(cLine[n])) cLine[n] = '.';
			nLen += sprintf(szBuf + nLen, "%c", cLine[n]);
		}
		nLen += sprintf(szBuf + nLen, "\n");
	}
	PrintLog(pfile, szBuf);
	return 0;
}

int PrintTraceHexLog(void * pData, int nSize){
 	FILE *fp;
 	int ret;
 	if ((fp = fopen(TRACE_FILE, "a")) != NULL) 	{
 		ret = PrintHexLog(fp, pData, nSize);
 		fclose(fp);	
	 	return(ret);
 	}
 	return -1;
}

int Verify(int bStatus, const char* szBuf, const char* szFile, int nLine){
	FILE *fp;
	char szFileLine[128], szError[128];
	if (!bStatus){
		memset(szFileLine, 0, sizeof(szFileLine));       
		memset(szError, 0, sizeof(szError));
		if (errno != 0) sprintf(szError, "\t> %0.64s\n", strerror(errno));
		if (szFile == NULL) strcpy(szFileLine, "\t> Invalid file name");
		else sprintf(szFileLine, "\t> In line %d file %0.32s", nLine, szFile);
		if (szBuf == NULL)  szBuf = "";
		fp = fopen(TRACE_FILE, "a");
		if (fp != NULL)	{
			PrintLog(fp, "%s[%d]\n%s%s", szBuf, getpid(), szError, szFileLine);
			fclose(fp);
		}
		errno = 0;
	}
	return bStatus;
}


TIMESTRU GetTime()
{
	TIMESTRU timestru;
	
	time_t time1;
	struct tm * when;
	
	time(&time1);
	when = localtime(&time1);
	
	timestru.nYear = when->tm_year + 1900;
	timestru.nMon = when->tm_mon + 1;
	timestru.nDay = when->tm_mday;
	
	timestru.nHour = when->tm_hour;
	timestru.nMin = when->tm_min;
	timestru.nSec = when->tm_sec;
	
	return timestru;
}

TIMESTRU GetOffsetTime(TIMESTRU timestru, int nOffsetSec)
{
	TIMESTRU timestruAfter;
	time_t ttime;
	struct tm when;
	
	memset(&when, 0, sizeof(when));
	when.tm_year = timestru.nYear - 1900;
	when.tm_mon  = timestru.nMon - 1;
	when.tm_mday = timestru.nDay;
	when.tm_hour = timestru.nHour;
	when.tm_min  = timestru.nMin;
	when.tm_sec  = timestru.nSec;
	
	ttime = mktime(&when) + nOffsetSec;
	
	when = *localtime(&ttime);
	
	timestruAfter.nYear = when.tm_year + 1900;
	timestruAfter.nMon = when.tm_mon + 1;
	timestruAfter.nDay = when.tm_mday;
	timestruAfter.nHour = when.tm_hour;
	timestruAfter.nMin = when.tm_min;
	timestruAfter.nSec = when.tm_sec;
	
	return timestruAfter;
}
